//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "cfile.h"
#include "win32module.h"
#include <string.h>

typedef Aura_ECode (*FileHelper_Open_Fun)(Aura_PWChar wszName, FILE *ppFile);
typedef Aura_ECode (*FileHelper_Read_Fun)(FILE pFile, Aura_UInt32 offset, Aura_UInt32 size, Aura_PVoid *ppBuf);
typedef Aura_ECode (*FileHelper_GetSize_Fun)(FILE pFile, Aura_UInt32 *pSize); 
typedef Aura_ECode (*FileHelper_Close_Fun)(FILE pFile);

enum FILEHLPFUNCTIONNAMES
{
    FileHelper_Open = 0,
    FileHelper_Read,
    FileHelper_GetSize,
    FileHelper_Close
};

char *g_FileHlpFunctionNames[] =
{
    "FileHelper_Open",
    "FileHelper_Read",
    "FileHelper_GetSize",
    "FileHelper_Close"
};

Aura_PVoid g_hDll = AURA_NULL;
Aura_UInt32 *g_FileHlpFunctions = AURA_NULL;

Aura_ECode GetFileHlpFunction()
{
    Aura_ECode ec = Win32Module_Load((Aura_PWChar)L"filehelper.dll", 0, &g_hDll);
    if(AURA_FAILED(ec)) {
        return ec;
    }
    
    int count;
    count = sizeof(g_FileHlpFunctionNames)/sizeof(char *);
    
    g_FileHlpFunctions = (Aura_UInt32 *)Aura_malloc(count * sizeof(Aura_UInt32));
    if(NULL == g_FileHlpFunctions){
        return AURA_E_OUT_OF_MEMORY;
    }
    
    int i = 0;
    for(i = 0; i < count; i++) {
        ec = Win32Module_GetProcAddressByName(g_hDll, \
                g_FileHlpFunctionNames[i], &g_FileHlpFunctions[i]);
        if(AURA_FAILED(ec)) {
            return ec;
        }                
    }
   
    return AURA_NOERROR;
}


Aura_ECode ReleaseFileHlp()
{
    if(g_FileHlpFunctions) Aura_free(g_FileHlpFunctions);
    if(g_hDll) Win32Module_Unload(g_hDll); 
    return AURA_NOERROR;
}

Aura_ECode CLoadedFile::Init(Aura_PWChar wszFullPath)
{ 
    Aura_ECode ec;
    if(!g_hDll) {
        ec = GetFileHlpFunction();
        if(AURA_FAILED(ec)) {
            return ec;           
        }    
    }
    
    FileHelper_Open_Fun filehlp_Open = (FileHelper_Open_Fun)g_FileHlpFunctions[0];
   
    ec = filehlp_Open(wszFullPath, &m_File);
    if(AURA_FAILED(ec)) {
        return ec;
    }
 
    return AURA_NOERROR;
}


CLoadedFile::~CLoadedFile()
{   
	if(m_File) ((FileHelper_Close_Fun)g_FileHlpFunctions[3])(m_File);
    if(m_pBuffer) Aura_free(m_pBuffer);
    
    m_pBuffer = AURA_NULL;
}


Aura_UInt32 CLoadedFile::GetSize() 
{
    FileHelper_GetSize_Fun filehlp_getSize = (FileHelper_GetSize_Fun)g_FileHlpFunctions[2];
   
    Aura_UInt32   uFileSize;
    Aura_ECode ec = filehlp_getSize(m_File, &uFileSize);
    if(AURA_FAILED(ec)) {
        Aura_printf("GetSize Failed ec = %x. file:%s. line:%d. \n", 
                ec, __FILE__, __LINE__);   
        return 0;
    }
    
    return uFileSize;
}


Aura_ECode CLoadedFile::Read(Aura_UInt32 offset, Aura_UInt32 size, Aura_PVoid *ppBuf,
                 Aura_Bool bUseInterBuf)
{
    Aura_Byte *pBuf = AURA_NULL;
    Aura_ECode ec = AURA_NOERROR;
    
    if(bUseInterBuf){
        m_pBuffer = Aura_realloc(m_pBuffer, size); 
        if(AURA_NULL == m_pBuffer) {
            return AURA_E_OUT_OF_MEMORY;
        }
        
        memset(m_pBuffer, 0, size);
        
        *ppBuf = pBuf = (Aura_Byte*)m_pBuffer;
    } else {
        pBuf = (Aura_Byte*)*ppBuf;
        if(NULL == pBuf){
            return AURA_E_OUT_OF_MEMORY;
        }  
    }
    
    FileHelper_Read_Fun filehlp_read = (FileHelper_Read_Fun)g_FileHlpFunctions[1];
    
    ec = filehlp_read(m_File, offset, size, (Aura_PVoid *)&pBuf);
    if(AURA_FAILED(ec)) {
        Aura_printf("AuraFile_Read error. ec = %x. FILE:%s. LINE:%d\n", 
                ec, __FILE__, __LINE__);
        return ec;
    }

    return AURA_NOERROR;
}
